
#include <gomoku/core/StateStack.h>


namespace gomoku
{
    StateStack::StateStack()
        : _context()
    {}
    
    StateStack::~StateStack()
    {
        auto it = _states.begin();

        for (; it != _states.end(); ++it)
        {
            if (*it != 0)
                delete (*it);
        }
    }

    void StateStack::setContext(Context context)
    {
        _context = context;
    }

    void StateStack::handleEvent()
    {
        auto itr = _currents.rbegin();

        for (; itr != _currents.rend(); ++itr)
        {
            if (!(*itr)->handleEvent())
                break;
        }
    }

    void StateStack::update(float dt)
    {
        std::list<State *>::reverse_iterator itr = _currents.rbegin();

        for (; itr != _currents.rend(); ++itr)
        {
            if (!(*itr)->update(dt))
                break;
        }
        applyPendingChanges();
    }

    void StateStack::draw()
    {
        std::list<State *>::reverse_iterator itr = _currents.rbegin();

        for (; itr != _currents.rend(); ++itr)
            (*itr)->draw();
    }

    void StateStack::pushState(StateID stateID)
    {
        PendingChange p;

        p.action = Push;
        p.stateID = stateID;
        _pendingList.push_back(p);
    }

    void StateStack::popState()
    {
        _pendingList.pop_back();
    }

    void StateStack::clearStates()
    {
        _pendingList.clear();
    }

    bool StateStack::isEmpty() const
    {
        return _currents.empty();
    }

    void StateStack::applyPendingChanges()
    {
        std::list<PendingChange>::iterator it = _pendingList.begin();

        for (; it != _pendingList.end(); ++it)
        {
            switch ((*it).action)
            {
            case Push:
                pushState((*it).stateID);
                break;
            case Pop:
                popState();
                break;
            case Clear:
                clearStates();
                break;
            }
        }
    }
}
